package com.example.mykotlinapp

import android.content.Context
import android.util.AttributeSet

/**
 *
 *
 * @author zhudeshuai
 * @since 2019/7/2
 */

//内部类和嵌套类

class Day05Button : View(100, 100) {

    fun getStatus(): ButtonState = ButtonState()

    class ButtonState//不会持有外部类引用
}

class Day05Button2 : View(200, 200) {
    fun getStatus(): ButtonState = ButtonState()

    inner class ButtonState//inner修饰内部类，持有外部引用
}

//内部类访问外部类实例
class Outer {
    inner class Inner {
        fun getOuter(): Outer = this@Outer
    }
}

//密封类（sealed）,sealed隐含这个类是open的
sealed class Express {
    class A : Express()
    class B : Express()
}


private fun test50(express: Express): Int =
    when (express) {
        is Express.A -> 0
        is Express.B -> 1
    }

//初始化类
/*open class User(val nickName: String)//小括号之内就是主构造方法*/

//等价于上面
class User2 constructor(_nickName: String) {
    val nickName: String

    init {
        nickName = _nickName
    }

}

//默认值
/*class User3(val nickName: String, val isMarried: Boolean = false)

class TwitterUser(nickName: String) : User(nickName) {
    //TODO:
}*/

//私有构造，外部无法实例化该类
class Secretive private constructor() {

}

//多个构造方法
open class MyView {
    constructor(ctx: Context)
    constructor(ctx: Context, attr: AttributeSet?)
}

class MyButton : MyView {
    constructor(ctx: Context) : this(ctx, null) {

    }

    constructor(ctx: Context, attr: AttributeSet?) : super(ctx, attr) {

    }
}

//接口中声明属性
/*interface User {
    val nickName: String
}

class PrivateUser(override val nickName: String) : User

class SubscribingUser(val email: String) : User {
    override val nickName: String
        get() = email.substringBeforeLast("@")
}*/

interface User1 {
    val email: String
    val nickName: String
        get() = email.plus(nickName)
}

class User3(val name: String) {
    var address: String = "unspecified"
        set(value) {
            println(
                """
            Address was changed for $name:
            "$field" -> "$value"
        """.trimIndent()
            )
            field = value
        }
}

private fun test51() {
    val user = User3("zhudeshuai")
    user.address = "CN"
    user.address = "USA"
}

//修改访问器的可见性
class LengthCounter {
    var counter: Int = 0
        private set

    fun addWord(word: String) {
        counter += word.length
    }
}

private fun test52() {
    val lengthCounter = LengthCounter()
    lengthCounter.addWord("java")
    println(lengthCounter.counter)
}


//数据类和类委托(NOTE:kotlin中==就是调用equals方法。kotlin中===才是比较引用值，等同于Java的==)
class Client(val name: String, val postalCode: Int) {
    override fun toString() = "Client(name=$name, postalCode=$postalCode)"
    override fun equals(other: Any?): Boolean {
        return if (other == null || other !is Client)
            false
        else
            name == other.name && postalCode == other.postalCode
    }

    override fun hashCode(): Int {
        return name.hashCode() * 31 + postalCode
    }

}

private fun test53() {
    val client1 = Client("curry", 2203333)
    val client2 = Client("curry", 2203333)
    println(client1 == client2)
}


//hashCode方法与equals方法需要一起重写
private fun test54() {
    val hashSet = hashSetOf(Client("james", 232323))
    println(hashSet.contains(Client("james", 232323)))
}


//自动生成通用方法的实现（data修饰符）
data class Client2(val name: String, val postalCode: Int)

private fun test55() {
    val client1 = Client2("curry", 2203333)
    val client2 = Client2("curry", 2203333)
    val hashSet = hashSetOf(client1)
    println(client1 == client2)
    println(hashSet.contains(client2))
}

//copy方法
private fun test56() {
    val client1 = Client2("curry", 2203333)
    val client2 = client1.copy()
    println(client1 == client2)

}

//类委托（by关键字）
class DelegatingCollection<T>(innerList: Collection<T> = ArrayList()) : Collection<T> by innerList {

}


//委托
class CountingSet<T>(private val innerSet: MutableCollection<T> = HashSet()) : MutableCollection<T> by innerSet {
    var objectAdded = 0

    override fun add(element: T): Boolean {
        objectAdded++
        return innerSet.add(element)
    }

    override fun addAll(elements: Collection<T>): Boolean {
        objectAdded += elements.size
        return innerSet.addAll(elements)
    }
}


fun main() {
    test56()
}
